package city.spring.configure.mybatis;

import city.spring.configure.mybatis.handler.CurrentUserMetaObjectHandlerImpl;
import city.spring.configure.mybatis.handler.IMetaObjectHandler;
import city.spring.configure.mybatis.handler.SequenceKeyMetaObjectHandlerImpl;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.google.common.collect.ArrayListMultimap;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 自定义字段填充处理器
 *
 * @author HouKunLin
 * @date 2020/7/15 0015 15:29
 */
@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
    private final List<IMetaObjectHandler> handlers = new ArrayList<>();
    private final ArrayListMultimap<String, Field> multimap = ArrayListMultimap.create();

    public CustomMetaObjectHandler(IKeyGenerator keyGenerator, JdbcTemplate jdbcTemplate) {
        handlers.add(new SequenceKeyMetaObjectHandlerImpl(keyGenerator, jdbcTemplate));
        handlers.add(new CurrentUserMetaObjectHandlerImpl());

    }


    @Override
    public void insertFill(MetaObject metaObject) {
        // Reflector forClass = metaObject.getReflectorFactory().findForClass(metaObject.getOriginalObject().getClass());
        Class<?> aClass = metaObject.getOriginalObject().getClass();
        String className = aClass.getName();
        if (multimap.containsKey(className)) {
            multimap.get(className).forEach(field -> handler(metaObject, field));
            return;
        }
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            if (handler(metaObject, field)) {
                multimap.put(className, field);
            }
        }
    }

    private boolean handler(MetaObject metaObject, Field field) {
        boolean result = false;
        for (IMetaObjectHandler handler : handlers) {
            if (handler.run(this, metaObject, field)) {
                result = true;
            }
        }
        return result;
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    }
}
